/**
 * 
 */
package photosalvage.rs;

import static com.google.inject.matcher.Matchers.*;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;

import photosalvage.logging.MethodProfileLogInterceptor;
import photosalvage.logging.UserTrackingLogInterceptor;
import photosalvage.rs.photos.Photos;
import photosalvage.rs.top.TopPage;
import photosalvage.rs.users.Users;

import com.google.common.collect.ImmutableMap;
import com.google.inject.persist.PersistFilter;
import com.google.inject.servlet.ServletModule;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;

/**
 * @author shumpei
 * 
 */
public class RestModule extends ServletModule {

	static final Class<?>[] RESOURCE_CLASSES = new Class<?>[] {
		Photos.class,
		Users.class,
		TopPage.class
	};

	@Override
	protected void configureServlets() {
		List<String> patterns = new ArrayList<String>();
		for (Class<?> resourceClass : RESOURCE_CLASSES) {
			Path pathAnnotation = resourceClass.getAnnotation(Path.class);
			String path = pathAnnotation.value();
			patterns.add(path);
			patterns.add(path + "/*");
			bind(resourceClass);
			
		}
		// Interceptors
		{
			// Auth check
			AuthCheckInterceptor authCheckInterceptor = new AuthCheckInterceptor();
			requestInjection(authCheckInterceptor);
			
			// User tracking log
			UserTrackingLogInterceptor userTrackingLogInterceptor = new UserTrackingLogInterceptor();
			requestInjection(userTrackingLogInterceptor);
			
			// Method profile log
			MethodProfileLogInterceptor methodProfileLogInterceptor = new MethodProfileLogInterceptor();
			requestInjection(methodProfileLogInterceptor);
			
			bindInterceptor(annotatedWith(Path.class), annotatedWith(GET.class)
					.or(annotatedWith(POST.class)).or(annotatedWith(PUT.class))
					.or(annotatedWith(DELETE.class)).or(
							annotatedWith(OPTIONS.class)).or(
							annotatedWith(HEAD.class)).and(
							not(annotatedWith(AuthNotRequired.class))),
					authCheckInterceptor, userTrackingLogInterceptor, methodProfileLogInterceptor);
		}
		String pattern0 = patterns.get(0);
		String[] patternOthers = patterns.subList(1, patterns.size()).toArray(new String[0]);
		// use Guice Persist
		filter(pattern0, patternOthers).through(PersistFilter.class);
		// use Jersey's GuiceContainer
		filter(pattern0, patternOthers)
				.through(
						GuiceContainer.class,
						ImmutableMap
								.of("com.sun.jersey.config.property.JSPTemplatesBasePath",
										"/WEB-INF/jsp"));
	}
}
